/*******************************************************************************
 * Copyright (c) 2000, 2005 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package com.architexa.org.eclipse.gef.ui.palette.customize;

import com.architexa.org.eclipse.gef.ui.palette.PaletteMessages;
import com.architexa.org.eclipse.gef.ui.palette.PaletteViewerPreferences;

import java.util.HashMap;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.FontDialog;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Widget;

import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.resource.StringConverter;
import org.eclipse.ui.part.PageBook;


/**
 * @author Pratik Shah
 */
public class PaletteSettingsDialog 
	extends Dialog 
{
	
private PaletteViewerPreferences prefs;
private Label fontName;
private PageBook book;
private Control columnsPanel, detailsPanel, iconsPanel, listPanel;
private HashMap widgets = new HashMap();

/**
 * A HashMap to cache the various settings displayed in this dialog
 */
protected HashMap settings = new HashMap();

/**
 * HashMap keys used for caching the various settings displayed in this dialog.
 */
protected static final String
	CACHE_LAYOUT = "layout setting", //$NON-NLS-1$
	CACHE_COLUMNS_ICON_SIZE = "columns - use large icons", //$NON-NLS-1$
	CACHE_LIST_ICON_SIZE = "list - use large icons", //$NON-NLS-1$
	CACHE_ICONS_ICON_SIZE = "icons only - use large icons", //$NON-NLS-1$
	CACHE_DETAILS_ICON_SIZE = "details - use large icons", //$NON-NLS-1$
	CACHE_FONT = "font", //$NON-NLS-1$
	CACHE_COLLAPSE = "auto-collapse setting"; //$NON-NLS-1$

/**
 * The unique IDs for the various widgets.  These IDs can be used to retrieve
 * these widgets from the internal map (using {@link #getWidget(int)}), or to identify
 * widgets in {@link #buttonPressed(int)}.
 */
protected static final int
	LAYOUT_COLUMNS_VIEW_ID        = IDialogConstants.CLIENT_ID + 1,
	LAYOUT_LIST_VIEW_ID           = IDialogConstants.CLIENT_ID + 2,
	LAYOUT_ICONS_VIEW_ID          = IDialogConstants.CLIENT_ID + 3,
	LAYOUT_COLUMNS_ICON_SIZE_ID   = IDialogConstants.CLIENT_ID + 4,
	LAYOUT_LIST_ICON_SIZE_ID      = IDialogConstants.CLIENT_ID + 5,
	LAYOUT_ICONS_ICON_SIZE_ID     = IDialogConstants.CLIENT_ID + 6,
	LAYOUT_DETAILS_ICON_SIZE_ID   = IDialogConstants.CLIENT_ID + 7,
	COLLAPSE_NEVER_ID             = IDialogConstants.CLIENT_ID + 8,
	COLLAPSE_ALWAYS_ID            = IDialogConstants.CLIENT_ID + 9,
	COLLAPSE_NEEDED_ID            = IDialogConstants.CLIENT_ID + 10,
	APPLY_ID                      = IDialogConstants.CLIENT_ID + 11,
	LAYOUT_DETAILS_VIEW_ID        = IDialogConstants.CLIENT_ID + 12,
	FONT_CHANGE_ID                = IDialogConstants.CLIENT_ID + 13,
	DEFAULT_FONT_ID				  = IDialogConstants.CLIENT_ID + 14;

/**
 * Sub - classes that need to create their own unique IDs should do so by adding
 * to this ID.
 */
protected static final int CLIENT_ID = 16;

/**
 * Constructor
 * 
 * @param	parentShell		The parent shell, or <code>null</code> to create a  top - level
 * 							shell
 * @param	prefs		The PaletteViewerPreferences object that can provide access to 
 * 						and allow modification of the palette's settings.  It cannot be
 * 						<code>null</code>.
 */
public PaletteSettingsDialog(Shell parentShell, PaletteViewerPreferences prefs) {
	super(parentShell);
	this.prefs = prefs;
	setShellStyle(getShellStyle() | SWT.RESIZE | SWT.MAX);
}

/**
 * This method will be invoked whenever any <code>Button</code> created using 
 * {@link #createButton(Composite, int, String, int, ImageDescriptor)} or 
 * {@link Dialog#createButton(Composite, int, String, boolean)} is selected.
 * 
 * @see Dialog#buttonPressed(int)
 */
protected void buttonPressed(int buttonId) {
	Button b = getButton(buttonId);
	
	if (FONT_CHANGE_ID == buttonId) {
		handleChangeFontPressed();
	} else if (COLLAPSE_ALWAYS_ID == buttonId) {
		handleAutoCollapseSettingChanged(PaletteViewerPreferences.COLLAPSE_ALWAYS);
	} else if (COLLAPSE_NEVER_ID == buttonId) {
		handleAutoCollapseSettingChanged(PaletteViewerPreferences.COLLAPSE_NEVER);
	} else if (COLLAPSE_NEEDED_ID == buttonId) {
		handleAutoCollapseSettingChanged(PaletteViewerPreferences.COLLAPSE_AS_NEEDED);
	} else if (LAYOUT_COLUMNS_VIEW_ID == buttonId) {
		handleLayoutSettingChanged(PaletteViewerPreferences.LAYOUT_COLUMNS);
	} else if (LAYOUT_ICONS_VIEW_ID == buttonId) {
		handleLayoutSettingChanged(PaletteViewerPreferences.LAYOUT_ICONS);
	} else if (LAYOUT_LIST_VIEW_ID == buttonId) {
		handleLayoutSettingChanged(PaletteViewerPreferences.LAYOUT_LIST);
	} else if (LAYOUT_DETAILS_VIEW_ID == buttonId) {
		handleLayoutSettingChanged(PaletteViewerPreferences.LAYOUT_DETAILS);
	} else if (LAYOUT_DETAILS_ICON_SIZE_ID == buttonId) {
		handleIconSizeChanged(b.getSelection());
	} else if (LAYOUT_COLUMNS_ICON_SIZE_ID == buttonId) {
		handleIconSizeChanged(b.getSelection());
	} else if (LAYOUT_ICONS_ICON_SIZE_ID == buttonId) {
		handleIconSizeChanged(b.getSelection());
	} else if (LAYOUT_LIST_ICON_SIZE_ID == buttonId) {
		handleIconSizeChanged(b.getSelection());
	} else if (DEFAULT_FONT_ID == buttonId) {
		handleDefaultFontRequested();
	} else {
		super.buttonPressed(buttonId);
	}
}

/**
 * This method saves the various settings in this dialog, so that they can be restored
 * later on if "Cancel" is pressed.
 * 
 * @see	#restoreSettings()
 */
protected void cacheSettings() {
	settings.put(CACHE_LAYOUT, new Integer(prefs.getLayoutSetting()));
	settings.put(CACHE_COLLAPSE, new Integer(prefs.getAutoCollapseSetting()));
	settings.put(CACHE_FONT, prefs.getFontData());
	settings.put(CACHE_DETAILS_ICON_SIZE, 
			new Boolean(prefs.useLargeIcons(PaletteViewerPreferences.LAYOUT_DETAILS)));
	settings.put(CACHE_ICONS_ICON_SIZE, 
			new Boolean(prefs.useLargeIcons(PaletteViewerPreferences.LAYOUT_ICONS)));
	settings.put(CACHE_COLUMNS_ICON_SIZE, 
			new Boolean(prefs.useLargeIcons(PaletteViewerPreferences.LAYOUT_COLUMNS)));
	settings.put(CACHE_LIST_ICON_SIZE, 
			new Boolean(prefs.useLargeIcons(PaletteViewerPreferences.LAYOUT_LIST)));
}

/**
 * @see org.eclipse.jface.window.Window#close()
 */
public boolean close() {
	// Save or dump changes
	// This needs to be done here and not in the handle methods because the user can
	// also close the dialog with the 'X' in the top right of the window (which 
	// corresponds to a cancel).
	if (getReturnCode() != OK) {
		handleCancelPressed();
	}

	return super.close();
}

/**
 * @see org.eclipse.jface.window.Window#configureShell(Shell)
 */
protected void configureShell(Shell newShell) {
	newShell.setText(PaletteMessages.SETTINGS_DIALOG_TITLE);
	super.configureShell(newShell);
}

/**
 * This method should not be used to create buttons for the button bar.  Use
 * {@link Dialog#createButton(Composite, int, String, boolean)} for that.   This method
 * can be used to create any other button in the dialog.  The parent 
 * <code>Composite</code> must have a GridLayout.  These buttons will be  available
 * through {@link #getButton(int)} and {@link #getWidget(int)}.  Ensure that the various
 * buttons created by this method are given unique IDs.  Pass in a null image descriptor
 * if  you don't want the button to have an icon.  This method will take care of 
 * disposing the images that it creates.  {@link #buttonPressed(int)} will be called when
 * any of the buttons created by this method are  clicked (selected).
 * 
 * @param	parent		The composite in which the button is to be created
 * @param	id			The button's unique ID
 * @param	label		The button's text
 * @param	stylebits	The style bits for creating the button (eg., 
 * 						<code>SWT.PUSH</code) or <code>SWT.CHECK</code>)
 * @param	descriptor	The ImageDescriptor from which the image/icon for this
 * 						button should be created
 * @return				The newly created button for convenience
 */
protected Button createButton(Composite parent, int id, String label,
						int stylebits, ImageDescriptor descriptor) {
	Button button = new Button(parent, stylebits);
	button.setText(label);
	button.setFont(parent.getFont());
	GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
	button.setLayoutData(data);
	
	button.setData(new Integer(id));
	button.addSelectionListener(new SelectionAdapter() {
		public void widgetSelected(SelectionEvent event) {
			buttonPressed(((Integer) event.widget.getData()).intValue());
		}
	});
	widgets.put(new Integer(id), button);
	
	if (descriptor != null) {
		button.setImage(new Image(parent.getDisplay(), descriptor.getImageData()));
		button.addDisposeListener(new DisposeListener() {
			public void widgetDisposed(DisposeEvent e) {
				Image img = ((Button)e.getSource()).getImage();
				if (img != null && !img.isDisposed()) {
					img.dispose();
				}
			}
		});
	}
	
	return button;
}

/**
 * Creates and initializes (i.e., loads the current value from the
 * PaletteViewerPreferences) the part of the dialog where the options to close drawers
 * will be displayed.
 * 
 * @param container		The parent composite
 * @return	The newly created Control which has the drawer collapse options
 */
protected Control createDrawerCollapseOptions(Composite container) {
	Composite composite = new Composite(container, SWT.NONE);
	composite.setFont(container.getFont());
	GridLayout layout = new GridLayout(1, false);
	composite.setLayout(layout);
	
	Label label = new Label(composite, SWT.NONE);
	label.setFont(composite.getFont());
	label.setText(PaletteMessages.COLLAPSE_OPTIONS_TITLE);
	GridData data = new GridData();
	label.setLayoutData(data);
	
	Button b = createButton(composite, COLLAPSE_ALWAYS_ID, 
			PaletteMessages.COLLAPSE_ALWAYS_LABEL, SWT.RADIO, null);
	((GridData)b.getLayoutData()).horizontalIndent = 5;
	
	b = createButton(composite, COLLAPSE_NEEDED_ID, 
			PaletteMessages.COLLAPSE_AS_NEEDED_LABEL, SWT.RADIO, null);
	((GridData)b.getLayoutData()).horizontalIndent = 5;
		
	b = createButton(composite, COLLAPSE_NEVER_ID, 
			PaletteMessages.COLLAPSE_NEVER_LABEL, SWT.RADIO, null);
	((GridData)b.getLayoutData()).horizontalIndent = 5;
	
	// Load auto - collapse settings
	b = null;
	int collapse = prefs.getAutoCollapseSetting();
	switch (collapse) {
		case PaletteViewerPreferences.COLLAPSE_ALWAYS:
			b = getButton(COLLAPSE_ALWAYS_ID);
			break;
		case PaletteViewerPreferences.COLLAPSE_AS_NEEDED:
			b = getButton(COLLAPSE_NEEDED_ID);
			break;
		case PaletteViewerPreferences.COLLAPSE_NEVER:
			b = getButton(COLLAPSE_NEVER_ID);
	}
	b.setSelection(true);

	return composite;
}

/**
 * Creates and initializes (i.e. loads the current settings from PaletteViewerPreferences)
 * the options for details layout.
 * 
 * @param parent	the parent composite
 * @return the newly created Control
 */
protected Control createDetailsOptions(Composite parent) {
	Control contents = createOptionsPage(parent, PaletteMessages.SETTINGS_OPTIONS_DETAILS,
	                                     LAYOUT_DETAILS_ICON_SIZE_ID);
	getButton(LAYOUT_DETAILS_ICON_SIZE_ID).setSelection(
			prefs.useLargeIcons(PaletteViewerPreferences.LAYOUT_DETAILS));
	return contents;
}

/**
 * @see org.eclipse.jface.dialogs.Dialog#createDialogArea(Composite)
 */
protected Control createDialogArea(Composite parent) {
	Composite composite = (Composite)super.createDialogArea(parent);
	GridLayout layout = (GridLayout)composite.getLayout();
	layout.horizontalSpacing = 0;
	layout.numColumns = 2;
	
	Control child = createFontSettings(composite);
	GridData data = new GridData(GridData.FILL_HORIZONTAL);
	data.horizontalSpan = 2;
	data.horizontalIndent = 5;
	child.setLayoutData(data);
	
	Label label = new Label(composite, SWT.SEPARATOR | SWT.HORIZONTAL);
	data = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
	data.horizontalSpan = 2;
	label.setLayoutData(data);
	
	child = createLayoutSettings(composite);
	data = new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.FILL_VERTICAL);
	data.horizontalSpan = 2;
	data.horizontalIndent = 5;
	child.setLayoutData(data);
	
	label = new Label(composite, SWT.SEPARATOR | SWT.HORIZONTAL);
	data = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
	data.horizontalSpan = 2;
	label.setLayoutData(data);
	
	child = createDrawerCollapseOptions(composite);
	data = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
	data.horizontalSpan = 2;
	data.horizontalIndent = 5;
	child.setLayoutData(data);
	
	label = new Label(parent, SWT.SEPARATOR | SWT.HORIZONTAL);
	data = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
	data.horizontalSpan = 2;
	label.setLayoutData(data);
	
	cacheSettings();
	
	return composite;
}

/**
 * Creates and initializes (i.e. loads the current settings from PaletteViewerPreferences)
 * the options for columns layout.
 * 
 * @param parent	the parent composite
 * @return the newly created Control
 */
protected Control createColumnsOptions(Composite parent) {
	Composite contents = (Composite)createOptionsPage(parent, 
			PaletteMessages.SETTINGS_OPTIONS_COLUMNS, LAYOUT_COLUMNS_ICON_SIZE_ID);
	getButton(LAYOUT_COLUMNS_ICON_SIZE_ID).setSelection(
			prefs.useLargeIcons(PaletteViewerPreferences.LAYOUT_COLUMNS));
	
//	final Button button = createButton(contents, -1,
//			PaletteMessages.SETTINGS_LAYOUT_COLUMNS_OVERRIDE_WIDTH, SWT.CHECK, null);
//	((GridData)button.getLayoutData()).horizontalSpan = 2;
//	
//	Composite container = new Composite(contents, SWT.NONE);
//	container.setFont(contents.getFont());
//	GridLayout layout = new GridLayout(2, false);
//	container.setLayout(layout);
//	GridData data = new GridData(GridData.FILL_HORIZONTAL | GridData.VERTICAL_ALIGN_FILL);
//	data.horizontalSpan = 2;
//	container.setLayoutData(data);
//	
//	final Label label = new Label(container, SWT.NONE);
//	label.setFont(container.getFont());
//	label.setText(PaletteMessages.SETTINGS_LAYOUT_COLUMNS_WIDTH);
//	data = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING 
//			| GridData.VERTICAL_ALIGN_BEGINNING);
//	label.setLayoutData(data);
//	label.setEnabled(false);
//	
//	final Text box = new Text(container, SWT.SINGLE | SWT.BORDER);
//	box.setFont(container.getFont());
////	box.setText("30");
//	box.setEnabled(false);
//	data = new GridData(GridData.FILL_HORIZONTAL | GridData.VERTICAL_ALIGN_BEGINNING);
//	data.widthHint = 50;
//	box.setLayoutData(data);
//	
//	button.addSelectionListener(new SelectionListener() {
//		public void widgetSelected(SelectionEvent e) {
//			label.setEnabled(!label.isEnabled());
//			box.setEnabled(!box.isEnabled());
//		}
//		public void widgetDefaultSelected(SelectionEvent e) {
//		}
//	});
	
	return contents;
}

/**
 * Creates and initializes (i.e. loads the current settings from PaletteViewerPreferences)
 * the part of the dialog that displays the font settings.
 * 
 * @param parent	the parent composite
 * @return the newly created Control
 */
protected Control createFontSettings(Composite parent) {
	Composite container = new Composite(parent, SWT.NONE);
	container.setFont(parent.getFont());
	GridLayout layout = new GridLayout(2, false);
	container.setLayout(layout);
	
	fontName = new Label(container, SWT.LEFT | SWT.WRAP);
	fontName.setFont(container.getFont());
	GridData data = new GridData(GridData.FILL_BOTH);
	data.verticalSpan = 2;
	fontName.setLayoutData(data);
	updateFontName();
	
	createButton(container, FONT_CHANGE_ID, PaletteMessages.SETTINGS_FONT_CHANGE, 
	             SWT.PUSH, null);
	
	createButton(container, DEFAULT_FONT_ID, PaletteMessages.SETTINGS_DEFAULT_FONT,
	             SWT.PUSH, null);
					
	return container;
}

/**
 * Creates and initializes (i.e. loads the current settings from PaletteViewerPreferences)
 * the options for icons layout.
 * 
 * @param parent	the parent composite
 * @return the newly created Control
 */
protected Control createIconsOnlyOptions(Composite parent) {
	Control contents = createOptionsPage(parent, 
			PaletteMessages.SETTINGS_OPTIONS_ICONS_ONLY, LAYOUT_ICONS_ICON_SIZE_ID);
	getButton(LAYOUT_ICONS_ICON_SIZE_ID).setSelection(
			prefs.useLargeIcons(PaletteViewerPreferences.LAYOUT_ICONS));
	return contents;
}

/**
 * Creates the part of the dialog that displays the various options for the selected
 * layout.
 * 
 * @param parent	the parent composite
 * @return the newly created Control
 */
protected Control createLayoutOptions(Composite parent) {
	Composite composite = new Composite(parent, SWT.NONE);
	composite.setFont(parent.getFont());
	GridLayout layout = new GridLayout(1, false);
	layout.marginWidth = 0;
	layout.marginHeight = 0;
	composite.setLayout(layout);
	
	Label label = new Label(composite, SWT.NONE);
	label.setFont(composite.getFont());
	label.setText(PaletteMessages.SETTINGS_LAYOUT_TITLE);
	GridData data = new GridData();
	label.setLayoutData(data);
	
	Button b = null;
	int[] modes = prefs.getSupportedLayoutModes();
	for (int i = 0; i < modes.length; i++) {
		switch(modes[i]) {
			case PaletteViewerPreferences.LAYOUT_COLUMNS:
				b = createButton(composite, LAYOUT_COLUMNS_VIEW_ID, 
						PaletteMessages.SETTINGS_COLUMNS_VIEW_LABEL, SWT.RADIO, null);
				((GridData)b.getLayoutData()).horizontalIndent = 5;
				break;
			case PaletteViewerPreferences.LAYOUT_LIST:
				b = createButton(composite, LAYOUT_LIST_VIEW_ID, 
						PaletteMessages.SETTINGS_LIST_VIEW_LABEL, SWT.RADIO, null);
				((GridData)b.getLayoutData()).horizontalIndent = 5;
				break;
			case PaletteViewerPreferences.LAYOUT_ICONS:	
				b = createButton(composite, LAYOUT_ICONS_VIEW_ID, 
						PaletteMessages.SETTINGS_ICONS_VIEW_LABEL, SWT.RADIO, null);
				((GridData)b.getLayoutData()).horizontalIndent = 5;
				break;
			case PaletteViewerPreferences.LAYOUT_DETAILS:	
				b = createButton(composite, LAYOUT_DETAILS_VIEW_ID, 
						PaletteMessages.SETTINGS_DETAILS_VIEW_LABEL, SWT.RADIO, null);
				((GridData)b.getLayoutData()).horizontalIndent = 5;
				break;
		}
	}
	
	// Load layout settings
	int layoutSetting = prefs.getLayoutSetting();
	switch (layoutSetting) {
		case PaletteViewerPreferences.LAYOUT_COLUMNS:
			b = getButton(LAYOUT_COLUMNS_VIEW_ID);
			break;
		case PaletteViewerPreferences.LAYOUT_ICONS:
			b = getButton(LAYOUT_ICONS_VIEW_ID);
			break;
		case PaletteViewerPreferences.LAYOUT_LIST:
			b = getButton(LAYOUT_LIST_VIEW_ID);
			break;
		case PaletteViewerPreferences.LAYOUT_DETAILS:
			b = getButton(LAYOUT_DETAILS_VIEW_ID);
			break;
	}
	b.setSelection(true);
	b.setFocus();

	return composite;
}

/**
 * Creates the part of the dialog that displays the lists the available layout modes.
 * 
 * @param parent	the parent composite
 * @return the newly created Control
 */
protected Control createLayoutSettings(Composite parent) {
	Composite composite = new Composite(parent, SWT.NONE);
	composite.setFont(parent.getFont());
	GridLayout layout = new GridLayout(2, false);
	composite.setLayout(layout);
	
	Control layoutOptions = createLayoutOptions(composite);
	GridData data = new GridData(GridData.VERTICAL_ALIGN_BEGINNING);
	layoutOptions.setLayoutData(data);
	
	book = new PageBook(composite, SWT.NONE);
	book.setFont(composite.getFont());
	data = new GridData(GridData.FILL_BOTH);
	book.setLayoutData(data);
	
	columnsPanel = createColumnsOptions(book);
	listPanel = createListOptions(book);
	iconsPanel = createIconsOnlyOptions(book);
	detailsPanel = createDetailsOptions(book);
	
	// Show the right page in the book
	handleLayoutSettingChanged(prefs.getLayoutSetting());
	
	return composite;
}

/**
 * Creates and initializes (i.e. loads the current settings from PaletteViewerPreferences)
 * the options for list layout.
 * 
 * @param parent	the parent composite
 * @return the newly created Control
 */
protected Control createListOptions(Composite parent) {
	Control composite = createOptionsPage(parent, PaletteMessages.SETTINGS_OPTIONS_LIST,
			LAYOUT_LIST_ICON_SIZE_ID);
	getButton(LAYOUT_LIST_ICON_SIZE_ID).setSelection(
			prefs.useLargeIcons(PaletteViewerPreferences.LAYOUT_LIST));
	return composite;
}

/**
 * This helper method is a result of code-factoring.  It creates a Group displaying the
 * given title and creates a "Use Large Icons" checkbox with the given buttonId in it. 
 * This method is used to create the options for the different layout modes.
 * 
 * @param parent	the parent composite
 * @param	title	The title for the group to be created.
 * @param	buttonId	The ID for the "Use Large Icons" checkbox to be created in the 
 * 						group.
 * @return the newly created Group
 */
protected Control createOptionsPage(Composite parent, String title, int buttonId) {
	Group contents = new Group(parent, SWT.NONE);
	contents.setFont(parent.getFont());
	GridLayout layout  = new GridLayout(1, false);
	contents.setLayout(layout);
	GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL 
	                            | GridData.VERTICAL_ALIGN_FILL);
	data.heightHint = 0;
	contents.setLayoutData(data);
	contents.setText(title);
	
	createButton(contents, buttonId, PaletteMessages.SETTINGS_USE_LARGE_ICONS_LABEL, 
			SWT.CHECK, null);
	
	return contents;
} 

/**
 * Returns the Button with the given id; or <code>null</code> if none was found.
 * 
 * @see org.eclipse.jface.dialogs.Dialog#getButton(int)
 */
protected Button getButton(int id) {
	Button button = null;
	Widget widget = getWidget(id);
	if (widget instanceof Button) {
		button = (Button)widget;
	}

	return button;
}

/**
 * The <code>Widget</code>s that were created with a unique ID and added to this class'
 * internal map can be retrieved through this method.
 * 
 * @param 	id	The unique ID of the Widget that you wish to retrieve
 * @return 	The Widget, if one with the given id exists.  <code>null</code>
 * 				otherwise.
 */
protected Widget getWidget(int id) {
	Widget widget = (Widget)widgets.get(new Integer(id));
	if (widget == null) {
		widget = super.getButton(id);
	}
	
	return widget;
}

/**
 * Called when any one of the "Auto - Collapse" radio buttons is clicked.  It 
 * changes the setting in the {@link com.architexa.org.eclipse.gef.ui.palette.PaletteViewerPreferences} 
 * object.
 * 
 * @param newSetting The flag for the new setting
 */
protected void handleAutoCollapseSettingChanged(int newSetting) {
	prefs.setAutoCollapseSetting(newSetting);
}

/**
 * This method is invoked when "Cancel" is invoked on the dialog.  It simply restores the
 * settings, thus undoing any changes made in this Dialog.
 */
protected void handleCancelPressed() {
	restoreSettings();
}

/**
 * This method is invoked when the user selects the "Change" font button.  It opens the
 * FontDialog to allow the user to change the font.
 */
protected void handleChangeFontPressed() {
	FontDialog dialog = new FontDialog(getShell());
	FontData data = prefs.getFontData();
	dialog.setFontList(new FontData[] {data});
	data = dialog.open();
	if (data != null) {
		prefs.setFontData(data);
	}
	updateFontName();
}

/**
 * This method is invoked when the user selects the "Restore Default" font button.  It
 * changes the font, in case it was different, to the default one, which is the Workbench
 * Dialog font.
 */
protected void handleDefaultFontRequested() {
	prefs.setFontData(JFaceResources.getDialogFont().getFontData()[0]);
	updateFontName();
}

/**
 * This method is invoked when the "Use Large Icons" checkbox is selected/deselected for
 * the currently active layout mode.
 * 
 * @param selection	indicates whether large icons are to be used or not.
 */
protected void handleIconSizeChanged(boolean selection) {
	prefs.setCurrentUseLargeIcons(selection);
}

/**
 * This method is called when any one of the "Layout" radio buttons is clicked.  It
 * changes the setting in the  {@link com.architexa.org.eclipse.gef.ui.palette.PaletteViewerPreferences}
 * object.
 * 
 * @param newSetting The flag for the new setting
 */
protected void handleLayoutSettingChanged(int newSetting) {
	prefs.setLayoutSetting(newSetting);
	switch (newSetting) {
		case PaletteViewerPreferences.LAYOUT_COLUMNS :
			showLayoutOptionsPage(columnsPanel);
			break;
		case PaletteViewerPreferences.LAYOUT_LIST :
			showLayoutOptionsPage(listPanel);
			break;
		case PaletteViewerPreferences.LAYOUT_ICONS :
			showLayoutOptionsPage(iconsPanel);
			break;
		case PaletteViewerPreferences.LAYOUT_DETAILS :
			showLayoutOptionsPage(detailsPanel);
			break;
		default :
			break;
	}
}

/**
 * Restores the cached settings, thus undoing any changes made since the last caching of
 * settings.
 * 
 * @see	#cacheSettings()
 */
protected void restoreSettings() {
	prefs.setFontData((FontData)settings.get(CACHE_FONT));
	prefs.setAutoCollapseSetting(((Integer)settings.get(CACHE_COLLAPSE)).intValue());
	prefs.setLayoutSetting(((Integer)settings.get(CACHE_LAYOUT)).intValue());
	prefs.setUseLargeIcons(PaletteViewerPreferences.LAYOUT_DETAILS, 
			((Boolean)settings.get(CACHE_DETAILS_ICON_SIZE)).booleanValue());
	prefs.setUseLargeIcons(PaletteViewerPreferences.LAYOUT_ICONS, 
			((Boolean)settings.get(CACHE_ICONS_ICON_SIZE)).booleanValue());
	prefs.setUseLargeIcons(PaletteViewerPreferences.LAYOUT_LIST, 
			((Boolean)settings.get(CACHE_LIST_ICON_SIZE)).booleanValue());
	prefs.setUseLargeIcons(PaletteViewerPreferences.LAYOUT_COLUMNS, 
			((Boolean)settings.get(CACHE_COLUMNS_ICON_SIZE)).booleanValue());
}

/**
 * This helper method is mainly a result of code-factoring.  It shows the given page
 * (which should be one of the controls showing the layout options) in the PageBook and
 * grows the dialog if necessary.
 * 
 * @param	page	One of the controls showing the layout options that already belongs to 
 * 					the PageBook book.
 */
protected void showLayoutOptionsPage(Control page) {
	// Show the page and grow the shell (if necessary) so that the page is completely 
	// visible
	Point oldSize = getShell().getSize();
	book.showPage(page);
	Point newSize = getShell().computeSize(SWT.DEFAULT, SWT.DEFAULT, true);
	int x = newSize.x - oldSize.x;
	x = (x < 0) ? 0 : x;
	int y = newSize.y - oldSize.y;
	y = (y < 0) ? 0 : y;
	if (x > 0 || y > 0) {
		getShell().setSize(oldSize.x + x, oldSize.y + y);
	}
}

/**
 * Updates the label showing the font's name to show the name of the current font.
 */
protected void updateFontName() {
	String name;
	if (prefs.getFontData().equals((JFaceResources.getDialogFont().getFontData()[0]))) {
		name = PaletteMessages.SETTINGS_WORKBENCH_FONT_LABEL;
	} else {
		name = StringConverter.asString(prefs.getFontData());
	}
	fontName.setText(PaletteMessages.SETTINGS_FONT_CURRENT + name);
}

}
